﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace PathFinding
{
	public partial class Form1 : Form
	{
		private int _stepSize = 10;
		private DijkstraPathFindingEngine _pathFindingEngine = null;
		private IIntersection[,] _grid = null;

		public Form1()
		{
			InitializeComponent();

			DijkstraPathFindingEngine dpfe = new DijkstraPathFindingEngine();
			dpfe.Step += new EventHandler(dpfe_Step);
			_pathFindingEngine = dpfe;

			_grid = CreateTestGrid();
			areaViewer1.AreaClicked += new EventHandler<AreaClickedEventArgs>(areaViewer1_AreaClicked);


		}


		void dpfe_Step(object sender, EventArgs e)
		{
			_stepSize++;
			if (_stepSize > 10)
			{
				_stepSize = 0;
				areaViewer1.Refresh();
			}
		}

		private IIntersection[] CreateTestMap()
		{
			IIntersection iBrussel = new BasicIntersection(3, 6);
			iBrussel.LocationName = "Brussel";

			IIntersection iParijs = new BasicIntersection(10, 12);
			iParijs.LocationName = "Parijs";

			IIntersection iLonden = new BasicIntersection(39, 24);
			iLonden.LocationName = "Londen";

			IIntersection iMadrid = new BasicIntersection(3, 20);
			iMadrid.LocationName = "Madrid";

			IIntersection iBoedapest = new BasicIntersection(30, 12);
			iBoedapest.LocationName = "Boedapest";

			IIntersection iDilsen = new BasicIntersection(17, 17);
			iDilsen.LocationName = "Dilsen";

			iBrussel.Neighbours = new IIntersection[] {
				iParijs,
				iMadrid
			};

			iParijs.Neighbours = new IIntersection[] {
				iBrussel,
				iBoedapest
			};

			iLonden.Neighbours = new IIntersection[] {
				iBoedapest,
				iMadrid,
				iDilsen
			};

			iMadrid.Neighbours = new IIntersection[] {
				iBrussel,
				iBoedapest,
				iLonden
			};

			iBoedapest.Neighbours = new IIntersection[] {
				iParijs,
				iMadrid,
				iLonden
			};

			iDilsen.Neighbours = new IIntersection[] {
				iLonden
			};

			return new IIntersection[] {
				iBrussel,
				iParijs,
				iLonden,
				iMadrid,
				iBoedapest,
				iDilsen
			};
		}
		private IIntersection[,] CreateTestGrid()
		{
			int width = 40;
			int height = 25;

			IIntersection[,] result = new IIntersection[width, height];

			for (int y = 0; y < height; y++)
			{
				for (int x = 0; x < width; x++)
				{
					result[x, y] = new BasicIntersection(x, y);
				}
			}

			
			for (int y = 5; y < height; y++)
			{
				result[10, y] = null;
			}
			
			for (int x = 12; x < width; x++)
			{
				result[x, 11] = null;
			}
			
			
			for (int y = 11; y < 22; y++)
			{
				result[15, y] = null;
			}

			for (int x = 16; x < 35; x++)
			{
				result[x, 18] = null;
			}


			Utils.FillNeighbours(result);

			return result;
		}

		private void button1_Click(object sender, EventArgs e)
		{
			areaViewer1.Reset();
			foreach (IIntersection i in _grid)
			{
				areaViewer1.AddIntersection(i);
			}
			//IIntersection start = _grid[1, 24];
			IIntersection start = _grid[35, 8];
			IIntersection destination = _grid[25, 15];
			IIntersection[] route = _pathFindingEngine.GetShortestRoute(start, destination);
			//WriteToConsole(route);
			areaViewer1.Start = start;
			areaViewer1.Destination = destination;
			areaViewer1.Route = route;
			areaViewer1.Refresh();
		}

		private void WriteToConsole(IIntersection[] route)
		{
			int height = _grid.GetLength(1);
			int width = _grid.GetLength(0);
			char[,] charGrid = new char[width, height];

			for (int y = 0; y < height; y++)
			{
				for (int x = 0; x < width; x++)
				{
					char c = (_grid[x, y] == null) ? 'X' : '.';

					charGrid[x, y] = c;
				}
			}

			if (route != null)
			{
				foreach (IIntersection i in route)
				{
					charGrid[i.X, i.Y] = 'P';
				}
			}
			

			for (int y = 0; y < height; y++)
			{
				for (int x = 0; x < width; x++)
				{
					Console.Write(charGrid[x, y]);
				}
				Console.WriteLine();
			}
		}

		private void button3_Click(object sender, EventArgs e)
		{
			areaViewer1.Reset();
			IIntersection[] cities = CreateTestMap();
			foreach (IIntersection i in cities)
			{
				areaViewer1.AddIntersection(i);
			}
			IIntersection start = cities[0];
			IIntersection dest = cities[5];
			areaViewer1.Start = start;
			areaViewer1.Destination = dest;

			IIntersection[] route = _pathFindingEngine.GetShortestRoute(start, dest);
			areaViewer1.Route = route;
			areaViewer1.Refresh();
		}

		private void button2_Click(object sender, EventArgs e)
		{
			areaViewer1.IScale = 10;
			areaViewer1.IntersectionSize = 10;
			IIntersection[,] grid = LoadGridFromFile();
			areaViewer1.Reset();
			foreach (IIntersection i in grid)
			{
				areaViewer1.AddIntersection(i);
			}

			IIntersection start = grid[1, 1];
			IIntersection destination = grid[119, 79];
			areaViewer1.Start = start;
			areaViewer1.Destination = destination;

			IIntersection[] route = _pathFindingEngine.GetShortestRoute(start, destination);
			areaViewer1.Route = route;
			areaViewer1.Refresh();

		}

		private IIntersection[,] LoadGridFromFile()
		{
			IIntersection[,] grid = null;
			List<string> lines = new List<string>();
			using (StreamReader sr = new StreamReader(@"grid.txt"))
			{
				string line = null;
				while ((line = sr.ReadLine()) != null)
				{
					lines.Add(line);
				}
			}

			if (lines.Count > 0)
			{
				grid = new IIntersection[lines[0].Length, lines.Count];

				for (int y = 0; y < lines.Count; y++)
				{
					for (int x = 0; x < lines[0].Length; x++)
					{
						grid[x, y] = (lines[y][x] == 'x') ?  null : new BasicIntersection(x, y);
					}
				}

				Utils.FillNeighbours(grid);
				
			}

			return grid;
		}

		
		#region Test custom grid
		private void button4_Click(object sender, EventArgs e)
		{
			areaViewer1.IScale = 10;
			areaViewer1.IntersectionSize = 10;
			areaViewer1.Reset();
			int width = 200;
			int height = 50;



			IIntersection[,] result = new IIntersection[width, height];

			for (int y = 0; y < height; y++)
			{
				for (int x = 0; x < width; x++)
				{
					result[x, y] = new BasicIntersection(x, y);
					areaViewer1.AddIntersection(result[x, y]);
				}
			}
			_grid = result;

			Utils.FillNeighbours(_grid);

			areaViewer1.Start = _grid[30, 18];
			areaViewer1.Destination = _grid[38, 20];
		}

		private void button5_Click(object sender, EventArgs e)
		{

			IIntersection[] route = _pathFindingEngine.GetShortestRoute(areaViewer1.Start, areaViewer1.Destination);
			areaViewer1.Route = route;
			areaViewer1.Refresh();
		}
		void areaViewer1_AreaClicked(object sender, AreaClickedEventArgs e)
		{
			//Console.WriteLine("({0}, {1})", e.X, e.Y);
			if (e.X >= 0 && e.Y >= 0 && _grid[e.X, e.Y] != null) areaViewer1.RemoveIntersection(_grid[e.X, e.Y]);
			List<IIntersection> n = Utils.GetNeighbours(_grid[e.X, e.Y], _grid);
			_grid[e.X, e.Y] = null;
			int xLen = _grid.GetLength(0);
			int yLen = _grid.GetLength(1);
			foreach (IIntersection i in n)
			{
				if (i != null) Utils.SetNeighbours(i, xLen, yLen, _grid);
			}
			//areaViewer1.Refresh();
		}
		#endregion
	}
}
